驱动程序实例(六):mpu6050(IIC + cdev)

您所在的位置:网站首页 linux iic设备驱动实例 驱动程序实例(六):mpu6050(IIC + cdev)

驱动程序实例(六):mpu6050(IIC + cdev)

2024-07-09 22:28:02| 来源: 网络整理| 查看: 265

在我们实际开发中,I2C 总线驱动一般芯片原厂会提供,我们开发一般是设计设备驱动。

本文结合之前对Linux内核的IIC子系统的分析 ,以及对字符设备的cdev接口的分析,本文将编写基于IIC总线与cdev接口的MPU6050设备的实例代码并对其进行分析。

IIC子系统分析:详见Linux IIC总线驱动框架。

字符设备的cdev接口分析:详见Linux字符设备驱动(一):cdev接口。

 

硬件接口:

  CPU:s5pv210;

  挂载IIC总线编号:0。

 

IIC从设备驱动挂载在IIC总线下,IIC总线管理着IIC从设备的设备信息(i2c_client)与设备驱动(i2c_driver)。因此,IIC从设备驱动的编写分为两个部分:注册IIC从设备信息、编写IIC从设备驱动程序。

在设备驱动程序中使用IIC总线,需确保Linux内核支持IIC。在menuconfig下做如下设置接口。

  Device Drivers  --->

     I2C support  --->  

1. 注册IIC从设备信息

在/kernel/arch/arm/mach-s5pv210/mach-x210.c文件中添加如下信息,向Linux内核注册IIC从设备信息。

static struct i2c_board_info mpu6050_i2c_devs0[] __initdata = { { I2C_BOARD_INFO("mpu6050", 0x2b),//构建i2c_board_info结构体,0x2b为从设备的地址 }, }; static void __init smdkc110_machine_init(void) { ... ... i2c_register_board_info(0, mpu6050_i2c_devs0, ARRAY_SIZE(mpu6050_i2c_devs0));//向内核注册IIC从设备信息,0表示该从设备挂载在IIC总线适配器0 ... ... } 2. 编写IIC从设备驱动程序

(1)mpu6050_common.h

将mpu6050_common.h文件添加至/kernel/drivers/i2c/busses目录下。

#ifndef _MPU6050_COMMON_H_ #define _MPU6050_COMMON_H_ #define MPU6050_MAGIC 'K' //mpu6050数据结构 union mpu6050_data { struct { short x; short y; short z; }accel; struct { short x; short y; short z; }gyro; unsigned short temp; }; //mpu6050的ioctl的命令定义 #define GET_ACCEL _IOR(MPU6050_MAGIC, 0, union mpu6050_data)//读取加速度计的数据 #define GET_GYRO _IOR(MPU6050_MAGIC, 1, union mpu6050_data)//读取陀螺仪的数据 #define GET_TEMP _IOR(MPU6050_MAGIC, 2, union mpu6050_data)//读取温度的数据 #endif mpu6050_common.h

 

(2)mpu6050_dev.h

mpu6050_dev.h文件是mpu6050的寄存器地址的定义文件,将其添加至添加至/kernel/drivers/i2c/busses目录下。

#ifndef _MPU6050_DEV_H_ #define _MPU6050_DEV_H_ #define SMPLRT_DIV 0x19 //陀螺仪采样率,典型值:0x07(125Hz) #define CONFIG 0x1A //低通滤波频率,典型值:0x06(5Hz) #define GYRO_CONFIG 0x1B //陀螺仪自检及测量范围,典型值:0x18(不自检,2000deg/s) #define ACCEL_CONFIG 0x1C //加速计自检、测量范围及高通滤波,典型值:0x18(不自检,2G,5Hz) #define ACCEL_XOUT_H 0x3B #define ACCEL_XOUT_L 0x3C #define ACCEL_YOUT_H 0x3D #define ACCEL_YOUT_L 0x3E #define ACCEL_ZOUT_H 0x3F #define ACCEL_ZOUT_L 0x40 #define TEMP_OUT_H 0x41 #define TEMP_OUT_L 0x42 #define GYRO_XOUT_H 0x43 #define GYRO_XOUT_L 0x44 #define GYRO_YOUT_H 0x45 #define GYRO_YOUT_L 0x46 #define GYRO_ZOUT_H 0x47 //陀螺仪z轴角速度数据寄存器(高位) #define GYRO_ZOUT_L 0x48 //陀螺仪z轴角速度数据寄存器(低位) #define PWR_MGMT_1 0x6B //电源管理,典型值:0x00(正常启用) #define WHO_AM_I 0x75 //IIC地址寄存器(默认数值0x68,只读) #define SlaveAddress 0x68 //MPU6050-I2C地址寄存器 #endif mpu6050_dev.h

 

(3)mpu6050.c

#include #include #include #include #include #include #include #include #include #include "mpu6050_dev.h" #include "mpu6050_common.h" #define DEV_MINOR 100 //IIC从设备的起始次设备号 #define DEV_CNT 1 //IIC从设备的个数 #define DEV_NAME "mpu6050" //IIC从设备名称 static struct i2c_client *mpu6050_client; static struct cdev mpu6050_dev; static dev_t mpu6050_devnum; //设备号 static struct class *mpu6050_class;//设备类 /* * 功能:向mpu6050从设备写入数据 * * 参数:struct i2c_client *client:指向mpu6050从设备 * const unsigned char reg:需写入的mpu6050的寄存器 * const unsigned char val:写入的数值 */ static void mpu6050_write_byte(struct i2c_client *client, const unsigned char reg, const unsigned char val) { char txbuf[2] = {reg, val};//数据缓存buffer //封装msg struct i2c_msg msg[2] = { [0] = { .addr = client->addr, .flags= 0, .len = sizeof(txbuf), .buf = txbuf, }, }; i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));//与从设备进行数据通信 } /* * 功能:向mpu6050从设备读取数据 * * 参数:struct i2c_client *client:指向mpu6050从设备 * const unsigned char reg:需读取的mpu6050的寄存器 * * 返回值:char:读取的数据 */ static char mpu6050_read_byte(struct i2c_client *client,const unsigned char reg) { char txbuf[1] = {reg};//数据缓冲buffer char rxbuf[1] = {0}; //封装msg struct i2c_msg msg[2] = { [0] = { .addr = client->addr, .flags = 0, .len = sizeof(txbuf), .buf = txbuf, }, [1] = { .addr = client->addr, .flags = I2C_M_RD, .len = sizeof(rxbuf), .buf = rxbuf, }, }; i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)); //与从设备进行数据通信 return rxbuf[0]; } //mpu6050硬件初始化 static void mpu6050_init(struct i2c_client *client) { mpu6050_write_byte(client, PWR_MGMT_1, 0x00); mpu6050_write_byte(client, SMPLRT_DIV, 0x07); mpu6050_write_byte(client, CONFIG, 0x06); mpu6050_write_byte(client, GYRO_CONFIG, 0x18); mpu6050_write_byte(client, ACCEL_CONFIG, 0x0); } static int mpu6050_open(struct inode *ip, struct file *fp) { return 0; } static int mpu6050_release(struct inode *ip, struct file *fp) { return 0; } static long mpu6050_ioctl(struct file *fp, unsigned int cmd, unsigned long arg) { int res = 0; union mpu6050_data data = {{0}}; switch(cmd) { //读取加速度计的数据 case GET_ACCEL: data.accel.x = mpu6050_read_byte(mpu6050_client,ACCEL_XOUT_L); data.accel.x|= mpu6050_read_byte(mpu6050_client,ACCEL_XOUT_H)name, client->flags,client->addr,client->adapter->nr,client->driver->driver.name ); /*********************************创建接口********************************/ cdev_init(&mpu6050_dev, &mpu6050_fops); //关联dev与fops alloc_chrdev_region(&mpu6050_devnum, DEV_MINOR, DEV_CNT, DEV_NAME);//自动分配设备号 cdev_add(&mpu6050_dev, mpu6050_devnum, DEV_CNT); //添加设备至设备链表 mpu6050_class = class_create(THIS_MODULE,DEV_NAME); //创建设备类 dev = device_create(mpu6050_class, NULL , mpu6050_devnum, "%s%d", DEV_NAME);//创建mpu6050设备 if (IS_ERR(dev)) { dbg("device create error\n"); goto out; } return 0; out: return -1; } static int mpu6050_remove(struct i2c_client *client) { dbg("remove\n"); device_destroy(mpu6050_class, mpu6050_devnum); class_destroy(mpu6050_class); unregister_chrdev_region(mpu6050_devnum,DEV_CNT); return 0; } //与mpu6050的设备信息匹配 static struct i2c_device_id mpu6050_ids[] = { {"mpu6050",0x2b}, {} }; //声明mpu6050_ids是i2c类型的一个设备表 MODULE_DEVICE_TABLE(i2c,mpu6050_ids); //定义并初始化从设备驱动信息 static struct i2c_driver mpu6050_driver = { .probe = mpu6050_probe, .remove = mpu6050_remove, .id_table = mpu6050_ids, .driver = { .name = "mpu6050", .owner = THIS_MODULE, }, }; static int __init mpu6050_i2c_init(void) { return i2c_add_driver(&mpu6050_driver);//注册设备驱动 } static void __exit mpu6050_i2c_exit(void) { i2c_del_driver(&mpu6050_driver); //注销设备驱动 } MODULE_AUTHOR("Lin"); MODULE_DESCRIPTION("mpu6050 driver"); MODULE_LICENSE("GPL"); module_init(mpu6050_i2c_init); module_exit(mpu6050_i2c_exit);


【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭